

<!DOCTYPE html>
<html lang="zh" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/walker_sue/img/favicon.png">
  <link rel="icon" type="image/png" href="/walker_sue/img/favicon.png">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="">
  <meta name="author" content="lk">
  <meta name="keywords" content="">
  <title>时间序列分析（二）Prophet - Walker_Sue</title>

  <link  rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.staticfile.org/github-markdown-css/4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/walker_sue/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.staticfile.org/highlight.js/10.0.0/styles/github-gist.min.css" />
    
  

  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/walker_sue/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script  src="/walker_sue/js/utils.js" ></script>
  <script  src="/walker_sue/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.3.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/walker_sue/">&nbsp;<strong>Walker</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/">
                <i class="iconfont icon-home-fill"></i>
                主页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/walker_sue/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-books"></i>
                文档
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/">
                    
                    主题博客
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/guide/">
                    
                    配置指南
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" target="_blank" rel="noopener" href="https://hexo.fluid-dev.com/docs/icon/">
                    
                    图标用法
                  </a>
                
              </div>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" href="javascript:">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner intro-2" id="background" parallax=true
         style="background: url('/walker_sue/img/default.png') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="container page-header text-center fade-in-up">
    <span class="h2" id="subtitle">
    
</span>




<div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-01-19 09:31" pubdate>
        January 19, 2021 am
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      3.1k 字
    </span>
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      37
       分钟
    </span>
  

  
  
</div>


</div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid">
  <div class="row">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-md">
      <div class="container nopadding-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto" id="post">
            <!-- SEO header -->
            <h1 style="display: none">时间序列分析（二）Prophet</h1>
            
            <div class="markdown-body" id="post-body">
              <div align='center' ><font size='10'>机器学习-BI</font></div>

<hr>
<div align='center' ><font size='5'>Week_02</font></div>
<div align='center' ><font size='5'>时间序列实战</font></div>

<hr>
<p><img src="prophet_summary.png" srcset="/walker_sue/img/loading.gif"><br><img src="prophet_summary2.png" srcset="/walker_sue/img/loading.gif"></p>
<blockquote>
<p><strong>Outline</strong></p>
<ul>
<li>prophet安装</li>
<li>Prophet预测模型</li>
<li>Prophet预测模型的优化</li>
</ul>
</blockquote>
<h2 id="一、时间预测算法prophet"><a href="#一、时间预测算法prophet" class="headerlink" title="一、时间预测算法prophet"></a><strong>一、时间预测算法prophet</strong></h2><h3 id="1-Windows环境下fbprophet包的安装"><a href="#1-Windows环境下fbprophet包的安装" class="headerlink" title="1 Windows环境下fbprophet包的安装"></a>1 Windows环境下fbprophet包的安装</h3><p>1.1 电脑安装anaconda环境，创建一个python3.7的conda环境。通过以下命令： <br></p>
<pre><code class="hljs python">conda create -n py37 python=<span class="hljs-number">3.7</span></code></pre>
<p>1.2 激活这个anaconda环境 <br></p>
<pre><code class="hljs python">conda activate py37</code></pre>
<p>1.3 conda安装 [有些慢，耐心~]</p>
<pre><code class="hljs python"><span class="hljs-comment"># **PyStan** is a Python interface to Stan, a package for Bayesian inference.</span>
<span class="hljs-comment"># Stan® is a state-of-the-art platform for statistical modeling and high-performance statistical computation. </span>
conda install pystan 
<span class="hljs-comment"># c problem</span>
conda install libpython m2w64-toolchain -c msys2  -f
<span class="hljs-comment"># install prophet </span>
conda install -c conda-forge fbprophet</code></pre>
<p>遇到问题: <br></p>
<pre><code class="hljs python">RemoveError: <span class="hljs-string">&#x27;requests&#x27;</span> <span class="hljs-keyword">is</span> a dependency of conda <span class="hljs-keyword">and</span> cannot be removed <span class="hljs-keyword">from</span> conda<span class="hljs-string">&#x27;s operating enviro</span></code></pre>
<p>直接升级conda: <br></p>
<pre><code class="hljs python">conda update conda</code></pre>
<p><a target="_blank" rel="noopener" href="https://github.com/facebook/prophet/issues/1670">“KeyError: ‘metric_file’#1670”</a></p>
<h3 id="2-Prophet预测模型"><a href="#2-Prophet预测模型" class="headerlink" title="2 Prophet预测模型"></a>2 Prophet预测模型</h3><p>prophet 是facebook在2017年开源的时间序列预测工具，<a target="_blank" rel="noopener" href="https://facebook.github.io/prophet/">github地址: https://facebook.github.io/prophet/</a> <br><br>Prophet是一个基于相加模型（ additive model）的时间预测，可以精准的拟合非线性的周期趋势 <br><br>对yearly、weekly和daily的周期性使用非线性拟合，亮点在于Prophet模型还添加了holidays（影响因子），可以很好的对节日（比如十一、春节等）带来的活跃数据的突变进行预测<br><br></p>
<h4 id="2-1-Prophet-简介"><a href="#2-1-Prophet-简介" class="headerlink" title="2.1 Prophet 简介"></a>2.1 Prophet 简介</h4><p>Prophet尝试处理许多商业时序数据中常见的困难：</p>
<ul>
<li>人类行为导致的季节性效应：周、月、年循环，公共假期的峰谷；</li>
<li>新产品和市场事件导致的趋势变动；</li>
<li>离群值。</li>
</ul>
<p>Prophet的适用对象和场景很广泛：</p>
<ul>
<li>面向广泛的分析师受众，这些受众可能在时序领域没有很多经验；</li>
<li>面向广泛的预测问题；</li>
<li>自动估计大量预测的表现，包括标出可能的问题，以供分析师进一步调查。</li>
</ul>
<p>Prophet 数据的输入和输出：<br><img src="prophet_plot.png" srcset="/walker_sue/img/loading.gif"><br><br><br>这是一个常见的时间序列场景，黑色表示原始的时间序列离散点，深蓝色的线表示使用时间序列来拟合所得到的取值，而浅蓝色的线表示时间序列的一个置信区间，也就是所谓的合理的上界和下界。prophet 所做的事情就是：</p>
<ul>
<li>输入已知的时间序列的时间戳和相应的值；</li>
<li>输入需要预测的时间序列的长度；</li>
<li>输出未来的时间序列走势。</li>
<li>输出结果可以提供必要的统计指标，包括拟合曲线，上界和下界等。</li>
</ul>
<p>fbprophet 所需要的时间序列输入格式使用csv 文件存储两列即可，第一列的名字是 ‘ds’, 第二列的名称是 ‘y’。第一列表示时间序列的时间戳，第二列表示时间序列的取值。通过 prophet 的计算，可以计算出 yhat，yhat_lower，yhat_upper，分别表示时间序列的预测值，预测值的下界，预测值的上界。<br></p>
<table>
<thead>
<tr>
<th>id</th>
<th align="center">y</th>
<th align="center">ds</th>
<th align="center">yhat</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td align="center">100</td>
<td align="center">2012-08-09</td>
<td align="center">265.732653</td>
</tr>
<tr>
<td>1</td>
<td align="center">414</td>
<td align="center">2012-08-10</td>
<td align="center">35.182235</td>
</tr>
<tr>
<td>2</td>
<td align="center">280</td>
<td align="center">2012-08-11</td>
<td align="center">-612.100115</td>
</tr>
<tr>
<td>3</td>
<td align="center">254</td>
<td align="center">2012-08-12</td>
<td align="center">-583.542886</td>
</tr>
<tr>
<td>4</td>
<td align="center">76</td>
<td align="center">2012-08-25</td>
<td align="center">-88.065521</td>
</tr>
</tbody></table>
<br>

<h4 id="2-2-Prophet-的算法实现"><a href="#2-2-Prophet-的算法实现" class="headerlink" title="2.2 Prophet 的算法实现"></a>2.2 Prophet 的算法实现</h4><p>在时间序列分析领域，有一种常见的分析方法叫做时间序列的分解（Decomposition of Time Series），它把时间序列 ${Y_t}$ 分成几个部分，分别是季节项 ${S_t}$ ，趋势项${T_t}$ ，剩余项${R_t}$。也就是说对所有的${t&gt;=0}$ ，都有: <br><br>$${Y_t = S_t + T_t + R_t}$$ <br><br>除了加法的形式，还有乘法的形式，也就是： <br><br>$${Y_t = S_t * T_t * R_t}$$ <br><br>以上式子等价于$${ln(Y_t) = ln(S_t) + ln(T_t) + ln(R_t)}$$ <br><br>一般来说，在实际生活和生产环节中，除了季节项，趋势项，剩余项之外，通常还有节假日的效应。所以，在 prophet 算法里面，作者同时考虑了以上四项，也就是：<br><br>$${Y_t = g_t + s_t + h_t + e}$$ <br><br>其中 ${g_t}$ 表示趋势项，它表示时间序列在非周期上面的变化趋势； ${s_t}$表示周期项，或者称为季节项，一般来说是以周或者年为单位； ${h_t}$ 表示节假日项，表示在当天是否存在节假日:${e}$ 表示误差项或者称为剩余项。Prophet 算法就是通过拟合这几项，然后最后把它们累加起来就得到了时间序列的预测值。<br></p>
<p><strong>prophet的优势：</strong></p>
<ul>
<li>处理数据丢失问题</li>
<li>趋势迁移问题（shifts in the trend）</li>
<li>异常的数据点（outliers）</li>
</ul>
<p><strong>趋势项模型g(t):</strong><br><br>在 Prophet 算法里面，趋势项有两个重要的函数，一个是基于逻辑回归函数（logistic function）的，另一个是基于分段线性函数（piecewise linear function）的。<br><br>$$f(x) = \frac{C}{1 + e^{-k(x-m)} }$$ <br><br>里的 ${C}$ 称为曲线的最大渐近值，${k}$表示曲线的增长率，${m}$表示曲线的中点。当${C=1,k=1,m=0}$ 时，恰好就是大家常见的 sigmoid 函数的形式。<br></p>
<h4 id="2-3-Prophet-的使用"><a href="#2-3-Prophet-的使用" class="headerlink" title="2.3 Prophet 的使用"></a>2.3 Prophet 的使用</h4><ul>
<li>输入格式</li>
</ul>
<p>因为 Prophet 所需要的两列名称是 ‘ds’ 和 ‘y’，其中，’ds’ 表示时间戳，’y’ 表示时间序列的值，因此通常来说都需要修改 pd.dataframe 的列名字。<br><br>如果原来的两列名字是 ‘timestamp’ 和 ‘value’ 的话，只需要这样写：<br><br><code>df = df.rename(columns=&#123;&#39;timestamp&#39;:&#39;ds&#39;, &#39;value&#39;:&#39;y&#39;&#125;)</code> <br><br>如果 ‘timestamp’ 是使用 unixtime 来记录的，需要修改成 YYYY-MM-DD hh:mm:ss 的形式：<br></p>
<p><code>df[&#39;ds&#39;] = pd.to_datetime(df[&#39;ds&#39;],unit=&#39;s&#39;)</code><br><br>在一般情况下，时间序列需要进行归一化的操作，而 pd.dataframe 的归一化操作也十分简单：<br></p>
<p><code>df[&#39;y&#39;] = (df[&#39;y&#39;] - df[&#39;y&#39;].mean()) / (df[&#39;y&#39;].std())</code><br></p>
<ul>
<li>模型初始化</li>
</ul>
<p>然后就可以初始化模型，然后拟合模型，并且进行时间序列的预测了。<br><br><code>初始化模型：m = Prophet() </code><br><br><code>拟合模型：m.fit(df) </code><br></p>
<ul>
<li>模型预测方法</li>
</ul>
<p>Prophet() 这个函数默认的使用 growth = ‘linear’ 这个增长函数，也可以写作<code>m = Prophet(growth = &#39;linear&#39;)</code>；如果想用 growth = ‘logistic’，需要这样写<code>m = Prophet(growth=&#39;logistic&#39;) </code>,并且需要设定边界上限df[‘cap’]和future[‘cap’] 。<br></p>
<ul>
<li>预测</li>
</ul>
<pre><code class="hljs python">计算预测值：periods 表示需要预测的点数，freq 表示时间序列的频率。
future = m.make_future_dataframe(periods=<span class="hljs-number">30</span>, freq=<span class="hljs-string">&#x27;min&#x27;</span>)
future.tail()
forecast = m.predict(future)</code></pre>
<br>
make_future_dataframe方法，将未来的日期扩展指定的天数，得到一个数据框。默认情况下，做会自动包含历史数据的日期，因此也可以用来查看模型对于历史数据的拟合效果 <br>
predict 方法，对每一行future 日期得到预测值（yhat ）预测 forecast 创建的对象应当是新的DataFrame，其中包含一列预测值 yhat ，以及成分的分析和置信区间<br>
plot_components方法，查看预测的成分分析<br>
查看forecast都有哪些列：print(forecast.columns)<br>

<ul>
<li>预测饱和增长</li>
</ul>
<p>Prophet在预测增长情况时，会存达到极值，比如总人口数等，这里称为承载能力（carrying capacity），这时上限就是趋于饱和<br>新建一列 cap 来指定承载能力的大小，通常情况下这个值应当通过市场规模的数据或专业知识来决定，比如<br><br>df[‘cap’] = 8.5<br>注意：DataFrame每行都必须指定 cap值，但不一定是恒定值，如果市场规模在不断地增长，那么 cap 也可以是不断增长的序列<br></p>
<ul>
<li>预测饱和减少（市场的最低floor）</li>
</ul>
<p>logistic增长模型还可以处理饱和最小值，方法与指定最大值的列的方式相同<br></p>
<ul>
<li>趋势突变点</li>
</ul>
<p>真实的时间序列数据往往存在一些突变点<br>Prophet 将自动监测到这些点，并对趋势做适当地调整<br>默认下， Prophet 会识别出 25 个潜在的突变点（均匀分布在在前 80% 的时间序列数据中），绝大多数突变点并不会包含在建模过程中<br>#显示突变点的位置</p>
<pre><code class="hljs python"><span class="hljs-keyword">from</span> fbprophet.plot <span class="hljs-keyword">import</span> add_changepoints_to_plot
fig = m.plot(forecast)
a = add_changepoints_to_plot(fig.gca(), m, forecast)</code></pre>
<ul>
<li>指定预测类型</li>
</ul>
<p>growth=’linear’或growth = “logistic” ; 默认的增长趋势为linear<br><br>如果使用growth=”logistic”，就需要指定cap，因为预测时需要用到cap，可以不指定floor，因为logistic默认的最小饱和值是0<br><br>m = Prophet(growth=’logistic’) <br><br>df[‘cap’] = 6 # 不设置会报错 <br></p>
<ul>
<li>模型的学习方式</li>
</ul>
<p>默认情况下为加性的，如果改成乘性的(multiplicative)，需要设置seasonality_mode=’multiplicative’<br></p>
<h3 id="3-Box-Cox变换"><a href="#3-Box-Cox变换" class="headerlink" title="3 Box-Cox变换"></a>3 Box-Cox变换</h3><h4 id="3-1-基本含义"><a href="#3-1-基本含义" class="headerlink" title="3.1 基本含义"></a>3.1 基本含义</h4><p>Box-Cox变换是一种广义幂变换方法，用于连续的响应变量不满足正态分布的情况。Box-Cox变换之后，可以一定程度上减小不可观测的误差和预测变量的相关性。Box-Cox变换的主要特点是引入一个参数lambda，通过数据本身估计该参数进而确定应采取的数据变换形式，Box-Cox变换可以明显地改善数据的正态性、对称性和方差相等性，对许多实际数据都是行之有效的。 <br><br>box-cox变换的目标有两个：一个是<strong>变换后，可以一定程度上减小不可观测的误差和预测变量的相关性</strong>。主要操作是对因变量转换，<strong>使得变换后的因变量于回归自变量具有线性相依关系，误差也服从正态分布，误差各分量是等方差且相互独立</strong>。第二个是用这个变换来<strong>使得因变量获得一些性质</strong>，比如在时间序列分析中的<strong>平稳性</strong>，或者<strong>使得因变量分布为正态分布</strong>。 <br></p>
<h4 id="3-2-公式表示"><a href="#3-2-公式表示" class="headerlink" title="3.2 公式表示"></a>3.2 公式表示</h4><p>$$y(\lambda) = \begin{cases} \frac{(y+c)^{\lambda}-1}{\lambda} \quad,\lambda \ne 0; \\ ln{y + c}\quad, \lambda = 0. \end{cases}$$ <br></p>
<ul>
<li>λ=1：没有进行实质上的转换</li>
<li>λ=1/2：平方根转换+线性转换</li>
<li>λ=1/3：立方根转换+线性转换</li>
<li>λ=0：log转换</li>
<li>λ=-1：与负倒数转换类似</li>
</ul>
<p>Box-Cox要求y&gt;0，否则在python中会报如下错误信息：<code>ValueError: Data must be positive.</code> <br><br>所以对于y&lt;0的情况，可以给y加上一个常数C进行调整.<br></p>
<h4 id="3-3-python实现"><a href="#3-3-python实现" class="headerlink" title="3.3 python实现"></a>3.3 python实现</h4><p>首先需要明确的是Box-Cox变换存在一个超参数lambda，这个超参数控制了数据的变化形式（如一中的公式所示），而且这个lambda也可以使用最大似然估计等方法进行计算得到。<br></p>
<h4 id="3-3-1-Box-Cox变换"><a href="#3-3-1-Box-Cox变换" class="headerlink" title="3.3.1 Box-Cox变换"></a>3.3.1 Box-Cox变换</h4><p>Box-Cox变换均在scipy模块之下，主要有以下两个地方：<br></p>
<pre><code class="hljs python"><span class="hljs-keyword">from</span> scipy.stats <span class="hljs-keyword">import</span> boxcox1   <span class="hljs-comment"># 1</span>
<span class="hljs-keyword">from</span> scipy.special <span class="hljs-keyword">import</span> boxcox2   <span class="hljs-comment"># 2</span>

<span class="hljs-comment"># 区别在于，1中包含了box-cox中的lambda计算（即不需要给函数boxcox输入参数lmbda，boxcox返回值中就有lambda）</span>
y, lambda0 = boxcox1(x, lmbda=<span class="hljs-literal">None</span>, alpha=<span class="hljs-literal">None</span>)
<span class="hljs-comment"># 而2中不包含lambda的计算，所以其函数参数必填的为数据data和lambda。</span>
y = boxcox2(x1, x2, *args, **kwargs)</code></pre>
<h4 id="3-3-2-反Box-Cox变换"><a href="#3-3-2-反Box-Cox变换" class="headerlink" title="3.3.2 反Box-Cox变换"></a>3.3.2 反Box-Cox变换</h4><p>通常我们在Box-cox变换之后，将预处理后的数据投入到模型中进行训练，如果变换处理的是标签，那么还需要对测试集的预测值进行反Box-Cox变换，Python实现如下：<br></p>
<pre><code class="hljs python"><span class="hljs-comment"># 方法1</span>
<span class="hljs-keyword">from</span> scipy.special <span class="hljs-keyword">import</span> inv_boxcox
y = inv_boxcox(x1, <span class="hljs-keyword">lambda</span>)
<span class="hljs-comment"># 方法2</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inverse_boxcox</span>(<span class="hljs-params">y, lambda_</span>):</span>
    <span class="hljs-keyword">return</span> np.exp(y) <span class="hljs-keyword">if</span> lambda_ == <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> np.exp(np.log(lambda_ * y + <span class="hljs-number">1</span>) / lambda_)

<span class="hljs-comment"># 简单流程示例</span>
<span class="hljs-comment"># 首先，我们准备数据，设置索引：</span>
train_df2 = train_df.copy().set_index(<span class="hljs-string">&#x27;ds&#x27;</span>)

<span class="hljs-comment"># 接着，我们应用Scipy的stats.boxcox函数（Box-Cox变换）。</span>
<span class="hljs-comment"># 这里它将返回两个值，第一个值是转换后的序列，第二个值是找到的最优λ值（最大似然）：</span>
train_df2[<span class="hljs-string">&#x27;y&#x27;</span>], lambda_prophet = stats.boxcox(train_df2[<span class="hljs-string">&#x27;y&#x27;</span>])
train_df2.reset_index(inplace=<span class="hljs-literal">True</span>)
<span class="hljs-comment"># 创建一个新Prophet模型，并重复之前的拟合-预测流程：</span>

m2 = Prophet()
m2.fit(train_df2)
future2 = m2.make_future_dataframe(periods=prediction_size)
forecast2 = m2.predict(future2)
<span class="hljs-comment"># 然后通过逆函数和已知的λ值反转Box-Cox变换：</span>

<span class="hljs-keyword">for</span> column <span class="hljs-keyword">in</span> [<span class="hljs-string">&#x27;yhat&#x27;</span>, <span class="hljs-string">&#x27;yhat_lower&#x27;</span>, <span class="hljs-string">&#x27;yhat_upper&#x27;</span>]:
    forecast2[column] = inverse_boxcox(forecast2[column],
                                       lambda_prophet)</code></pre>
<p>其中x为需要进行反Box-Cox变换的数据，lamda为训练集Box-Cox时使用的lambda，一般即为上文中stats.boxcox()返回的第二个参数。需要注意：如果在训练集Box-Cox变换时使用了C常数进行了自变量的非零处理，那么还需要再反变换之后减去这个C常数。<br></p>
<p>参考资料:</p>
<ul>
<li><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/52330017">Facebook 时间序列预测算法 Prophet 的研究</a></li>
<li><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/50288194">机器学习开放课程（终）：基于Facebook Prophet预测未来</a></li>
<li><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_44405644/article/details/108045328">BoxCox以及反变换的简介和Python实现</a></li>
</ul>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/walker_sue/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">机器学习</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/BI/">BI</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/">机器学习</a>
                    
                      <a class="hover-with-bg" href="/walker_sue/tags/%E6%97%B6%E9%97%B4%E5%BA%8F%E5%88%97%E5%88%86%E6%9E%90/">时间序列分析</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！</p>
              
              
                <div class="post-prevnext row">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/walker_sue/2021/01/25/week3-weekday/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">时间序列分析（三） 周期因子</span>
                        <span class="visible-mobile">Vorheriger</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/walker_sue/2020/12/30/BI-week1-ARIMA/">
                        <span class="hidden-mobile">时间序列分析（一）</span>
                        <span class="visible-mobile">Nächster</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;TOC</p>
  <div id="tocbot"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    
  </main>

  
    <a id="scroll-top-button" href="#" role="button">
      <i class="iconfont icon-arrowup" aria-hidden="true"></i>
    </a>
  

  
    <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">Suchen</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">Stichwort</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
  

  

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
  </div>
  

  

  
</footer>

<!-- SCRIPTS -->
<script  src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js" ></script>
<script  src="https://cdn.staticfile.org/twitter-bootstrap/4.4.1/js/bootstrap.min.js" ></script>
<script  src="/walker_sue/js/debouncer.js" ></script>
<script  src="/walker_sue/js/main.js" ></script>

<!-- Plugins -->


  
    <script  src="/walker_sue/js/lazyload.js" ></script>
  



  



  <script defer src="https://cdn.staticfile.org/clipboard.js/2.0.6/clipboard.min.js" ></script>
  <script  src="/walker_sue/js/clipboard-use.js" ></script>







  <script  src="https://cdn.staticfile.org/tocbot/4.11.1/tocbot.min.js" ></script>
  <script>
    $(document).ready(function () {
      var boardCtn = $('#board-ctn');
      var boardTop = boardCtn.offset().top;

      tocbot.init({
        tocSelector: '#tocbot',
        contentSelector: '#post-body',
        headingSelector: 'h1,h2,h3,h4,h5,h6',
        linkClass: 'tocbot-link',
        activeLinkClass: 'tocbot-active-link',
        listClass: 'tocbot-list',
        isCollapsedClass: 'tocbot-is-collapsed',
        collapsibleClass: 'tocbot-is-collapsible',
        collapseDepth: 0,
        scrollSmooth: true,
        headingsOffset: -boardTop
      });
      if ($('.toc-list-item').length > 0) {
        $('#toc').css('visibility', 'visible');
      }
    });
  </script>



  <script  src="https://cdn.staticfile.org/typed.js/2.0.11/typed.min.js" ></script>
  <script>
    function typing(id, title){
        var typed = new Typed('#' + id, {
            strings: [
              '  ',
              title + "&nbsp;",
            ],
            cursorChar: "_",
            typeSpeed: 70,
            loop: false,
        });
        typed.stop();
        $(document).ready(function () {
            $(".typed-cursor").addClass("h2");
            typed.start();
        });
    }
    
        typing("subtitle", "时间序列分析（二）Prophet")
    
  </script>


  <script  src="https://cdn.staticfile.org/anchor-js/4.2.2/anchor.min.js" ></script>
  <script>
    anchors.options = {
      placement: "right",
      visible: "hover",
      
    };
    var el = "h1,h2,h3,h4,h5,h6".split(",");
    var res = [];
    for (item of el) {
      res.push(".markdown-body > " + item)
    }
    anchors.add(res.join(", "))
  </script>



  <script  src="/walker_sue/js/local-search.js" ></script>
  <script>
    var path = "/walker_sue/local-search.xml";
    var inputArea = document.querySelector("#local-search-input");
    inputArea.onclick = function () {
      searchFunc(path, 'local-search-input', 'local-search-result');
      this.onclick = null
    }
  </script>



  <script  src="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.staticfile.org/fancybox/3.5.7/jquery.fancybox.min.css" />

  <script>
    $('#post img:not(.no-zoom img, img[no-zoom]), img[zoom]').each(
      function () {
        var element = document.createElement('a');
        $(element).attr('data-fancybox', 'images');
        $(element).attr('href', $(this).attr('src'));
        $(this).wrap(element);
      }
    );
  </script>





  

  
    <!-- MathJax -->
    <script>
      MathJax = {
        tex: {
          inlineMath: [['$', '$'], ['\\(', '\\)']]
        },
        options: {
          renderActions: {
            findScript: [10, doc => {
              document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
                const display = !!node.type.match(/; *mode=display/);
                const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
                const text = document.createTextNode('');
                node.parentNode.replaceChild(text, node);
                math.start = { node: text, delim: '', n: 0 };
                math.end = { node: text, delim: '', n: 0 };
                doc.math.push(math);
              });
            }, '', false],
            insertedScript: [200, () => {
              document.querySelectorAll('mjx-container').forEach(node => {
                let target = node.parentNode;
                if (target.nodeName.toLowerCase() === 'li') {
                  target.parentNode.classList.add('has-jax');
                }
              });
            }, '', false]
          }
        }
      };
    </script>

    <script async src="https://cdn.staticfile.org/mathjax/3.0.5/es5/tex-svg.js" ></script>

  











</body>
</html>
